package org.amn.concurrent;

import java.io.File;
import java.util.Random;

import org.amn.dto.IndexDTO;
import org.amn.file.FileManager;
import org.amn.file.FileStatus;
import org.amn.file.FileUtils;
import org.apache.log4j.Logger;

import com.bea.core.repackaged.springframework.util.Assert;

/**
 * <p>
 * 描述:消息通知处理者
 * </p>
 *
 * @see
 * @author yangjun1120@gmail.com
 *
 */
public class Worker implements Runnable {
    private static Logger logger = Logger.getLogger(Worker.class);

    private IindexQueue<IndexDTO> q;

    private boolean stop = false;

    private static String enqueuePath;

    private static String successPath;

    private static String exceptionPath;

    private static Random r = new Random();

    public Worker(FileManager fileManager, IindexQueue<IndexDTO> queue) {
        if (enqueuePath == null) {
            enqueuePath = fileManager.getPath(FileStatus.ENQUEUE);
        }

        if (successPath == null) {
            successPath = fileManager.getPath(FileStatus.SUCCESS);
        }

        if (exceptionPath == null) {
            exceptionPath = fileManager.getPath(FileStatus.EXCEPTION);
        }

        this.q = queue;
    }

    @Override
    public void run() {

        //while (!stop) {
        try {
            if (logger.isInfoEnabled()) {
                logger.info("" + this.hashCode() + " heartbeat.");
            }
            doWork();

            //Thread.sleep(5000);
        } catch (Throwable e) {
            logger.error("worker run exception", e);
        }

        //}
    }

    private void doWork() {
        while (!q.isEmpty()) {
            IndexDTO d = q.poll();

            //chekc file exist()
            if (d != null) {
                File f = new File(d.getPath());
                if (f.exists()) {

                    try {

                        doSomething(d);
                        if ((!moveFile(f, enqueuePath, successPath)) && (!moveFile(f, enqueuePath, exceptionPath))) {
                            FileUtils.deleteFile(f);//防止重复,内容可以在dosomething方法来log
                        }

                    } catch (Exception e) {
                        logger.error("business exception,file:" + f.getName() + ",indext id:" + d.getId(), e);
                        if (!moveFile(f, enqueuePath, exceptionPath)) {
                            FileUtils.deleteFile(f);//防止重复,内容可以在dosomething方法来log
                        }

                    }

                }

            }

        }

        if (logger.isDebugEnabled()) {
            logger.debug("sleep!");
        }

        sleepRandom();

    }

    private boolean moveFile(File f, String source, String dest) {
        Assert.notNull(f, "File is not null");
        Assert.notNull(source, "source path is not null");
        Assert.notNull(dest, "destination path is not null");

        source = FileUtils.formatPath(source);
        dest = FileUtils.formatPath(dest);
        String fName = f.getName();
        String absolutePath = f.getAbsolutePath();

        //正常待处理
        String destPath = dest;
        try {

            String folder = absolutePath.substring(absolutePath.indexOf(source) + source.length(),
                    absolutePath.indexOf(fName) - 1);

            String newFileName = destPath + File.separator + folder + File.separator + fName;

            if (FileUtils.renameTo(f, newFileName)) {
                return true;
            } else {
                logger.error("failure to rename file,source path:" + absolutePath + ",destination path:" + newFileName);
                return false;
            }

        } catch (Exception se) {
            logger.error("IOException", se);

        }

        return false;

    }

    public void doSomething(IndexDTO d) {
        try {
            Thread.sleep(500);
            //最重要是对file的log关键文件信息
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread:" + Thread.currentThread().getId() + ":" + System.currentTimeMillis() + d
                + " dosomething!");
    }

    private void sleepRandom() {
        try {
            Thread.sleep(r.nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public boolean isStop() {
        return stop;
    }

    public void stop() {
        this.stop = true;
    }

    public static void main(String[] args) throws Exception {

    }
}
